package cn.edu.hbpu.service;

import cn.edu.hbpu.common.page.PageQueryBean;
import cn.edu.hbpu.common.page.PageQueryCondition;
import cn.edu.hbpu.common.utils.DateUtils;
import cn.edu.hbpu.mapper.AttendMapper;
import cn.edu.hbpu.pojo.Attend;
import cn.edu.hbpu.pojo.Student;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by yuwenteng on 2017/9/19.
 */
@Service("attendServiceImpl")
public class AttendServiceImpl implements AttendService {

    private static final int NOON_HOUR = 12;
    private static final int NOON_MINUTE = 00;

    /**
     * 早签到时间
     */
    private static final int MORNING_HOUR = 8;
    private static final int MORNING_MINUTE = 00;

    /**
     * 晚签到时间
     */
    private static final int EVENING_HOUR = 17;
    private static final int EVENING_MINUTE = 00;

    /**
     * 考勤状态 1 正常 2 异常
     */
    private static final byte ATTEND_NORMAL = 1;
    private static final byte ATTEND_UNNORMAL = 2;

    /**
     * 一上午缺勤和一下午缺勤
     */
    private static final Integer ABSENCE_ALLMORNING = 240;
    private static final Integer ABSENCE_ALLEVENING = 300;

    /**
     * 周六和周日
     */
    private static final Integer STAURDAY = 6;
    private static final Integer SUNDAY = 7;

    @Autowired
    private AttendMapper attendMapper;

    /**
     * @Author yuwenteng
     * @Date 2017/9/22 22:42
     * @Description 完成考勤签到的业务逻辑，向数据库插入考勤数据
     */
    @Transactional
    public void signAttendance(Attend attend) {
        Date date = new Date();
        attend.setAttendDate(date);
        attend.setAttendWeek((byte) DateUtils.getCurrentWeek());
        Date noon = DateUtils.getDate(NOON_HOUR, NOON_MINUTE);
        Date morning = DateUtils.getDate(MORNING_HOUR, MORNING_MINUTE);
        Date evening = DateUtils.getDate(EVENING_HOUR, EVENING_MINUTE);
        //查看当前数据库中是否存在考勤记录
        Attend attendCurrent = attendMapper.selectBySno(attend.getSno());
        //如果考勤记录记录不存在
        if (attendCurrent == null) {
            if (date.compareTo(noon) <= 0) {
                //如果是早签到，设置早签到时间
                attend.setAttendMorning(date);
                if (date.compareTo(morning) >= 0) {
                    //如果签到时间迟于上午8点，算迟到，置为异常
                    attend.setAttendStatus(ATTEND_UNNORMAL);
                    //通过工具类算出缺勤时长
                    attend.setAbsenceMorning(DateUtils.getAbsenceMinute(morning, date));
                }
            } else {
                //如果是晚签到，设置晚签到时间
                attend.setAttendEvening(date);
                if (date.compareTo(evening) <= 0) {
                    //如果签到时间早于下午5点，算迟到，置为异常
                    attendCurrent.setAttendStatus(ATTEND_UNNORMAL);
                    attendCurrent.setAbsenceEvening(DateUtils.getAbsenceMinute(date, evening));
                }
            }
            attendMapper.insertSelective(attend);
        } else {
            //签到记录存在
            if (date.compareTo(noon) <= 0) {
                //如果是早签到的话，直接返回
                return;
            } else {
                //否则是晚签到，修改数据库晚签到信息
                attendCurrent.setAttendEvening(date);
                if (date.compareTo(evening) <= 0) {
                    //如果签到时间早于下午5点，算迟到，置为异常
                    attendCurrent.setAttendStatus(ATTEND_UNNORMAL);
                    attendCurrent.setAbsenceEvening(DateUtils.getAbsenceMinute(date, evening));
                }
            }
            //更新考勤信息
            attendMapper.updateByPrimaryKey(attendCurrent);
        }
        /**
         *@Author yuwenteng
         *@Date 2017/9/19 23:12
         *@Description
         * 需要排除三种异常：
         * ①上午没签到,下午签到时间晚于5点，数据库中是正常，实际异常
         * ②上午签到时间早于8点，下午没签到，数据库中是正常，实际异常
         * ③上午没签到，下午也没签到的，数据库无考勤信息，属于异常
         */
    }

    /**
     * @Author yuwenteng
     * @Date 2017/9/20 11:25
     * @Description 分页查询考勤信息
     */
    public PageQueryBean findAttendceInfo(PageQueryCondition pageQueryCondition) {
        //根据查询条件查询数据库中attend表中总的记录数count
        int count = attendMapper.selectCountOfAttend(pageQueryCondition);
        PageQueryBean pageQueryBean = new PageQueryBean();
        if (count > 0) {
            //如果表中存在考勤记录，根据查询条件查询分页的考勤结果
            List<Attend> attendList = attendMapper.selectAttendceInfo(pageQueryCondition);
            //将数据封装到PageQueryBean中回送给页面使用
            pageQueryBean.setCurrentPage(pageQueryCondition.getCurrentPage());
            pageQueryBean.setItems(attendList);
            pageQueryBean.setPageSize(pageQueryCondition.getPageSize());
            pageQueryBean.setTotalRows(count);
        }
        return pageQueryBean;
    }

    /**
     * @Author yuwenteng
     * @Date 2017/9/22 22:43
     * @Description 完成利用quartz定时任务清除数据库存在的异常数据的业务逻辑
     */
    @Transactional
    public void checkTableAttend() {
        /**
         * ①上午没签到,下午签到时间晚于5点，数据库中是正常，实际异常
         */
        List<Attend> morningAttendList = attendMapper.selectAttendMorningNull();
        if (CollectionUtils.isNotEmpty(morningAttendList)) {
            for (Attend attend : morningAttendList) {
                //更新异常数据
                attend.setAbsenceMorning(ABSENCE_ALLMORNING);
                attend.setAttendStatus(ATTEND_UNNORMAL);
                //将更新数据结果存入数据库中
                attendMapper.updateByPrimaryKey(attend);
            }
        }
        /**
         * ②上午签到时间早于8点，下午没签到，数据库中是正常，实际异常
         */
        List<Attend> eveningAttendList = attendMapper.selectAttendEveningNull();
        if (CollectionUtils.isNotEmpty(eveningAttendList)) {
            for (Attend attend : eveningAttendList) {
                //更新异常数据
                attend.setAbsenceEvening(ABSENCE_ALLEVENING);
                attend.setAttendStatus(ATTEND_UNNORMAL);
                //将更新数据结果存入数据库中
                attendMapper.updateByPrimaryKey(attend);
            }
        }
        /**
         * ③上午没签到，下午也没签到的，数据库无考勤信息，属于异常
         */
        List<Student> stuList = attendMapper.selectSnoAllNull();
        if (CollectionUtils.isNotEmpty(stuList)) {
            Date date = new Date();
            List<Attend> list = new ArrayList<Attend>();
            for (Student student : stuList) {
                Attend attend = new Attend();
                //更新异常数据
                attend.setSno(student.getSno());
                attend.setAttendDate(date);
                int currentWeek = DateUtils.getCurrentWeek();
                attend.setAttendWeek((byte) currentWeek);
                //如果是周六或周日，不算异常数据，排除这种情况
                if (currentWeek != STAURDAY && currentWeek != SUNDAY) {
                    attend.setAbsenceMorning(ABSENCE_ALLMORNING);
                    attend.setAbsenceEvening(ABSENCE_ALLEVENING);
                    attend.setAttendStatus(ATTEND_UNNORMAL);
                } else {
                    attend.setAttendStatus(ATTEND_NORMAL);
                }
                //将attend存入到list容器中
                list.add(attend);
            }
            //利用mybatis动态sql批量插入attend记录
            attendMapper.insertBatch(list);
        }
    }
}
